package top.riske.animalhazardassessment.ai;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.alibaba.dashscope.utils.Constants;
import io.reactivex.Flowable;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.Semaphore;

/**
 * created by vital on 2025/3/16 下午12:35
 */
@Slf4j
@Service
public class DeepSeekService {

    @Resource
    private RestTemplate restTemplate;

    private final static String API_KEY = "sk-bd9c0543e5084f15b4534a6a99ec5893";

    // 系统消息
    private static final String SystemMessage = "你是一个宠物狗危险性评估助手，请根据接收到的文本内容，评估危险性，需要从各方面评估，包括" +
            "animalAge:动物年龄，species:物种，towline：是否牵绳，" +
            "healthy:健康状况（0-健康，1-生病），physique:体型（0-微型，1-小型，2-中型，3-大型），" +
            "protectedFood:护食程度（0-无，1-低吼，3-龇牙，4-扑咬），" +
            "vaccines:是否打疫苗,返回格式为json格式，不要有```json这些东西，纯json信息，请不要提及这些参数信息，其中，评估报告不低于500字，" +
            "{risk:90,description:''},risk为总的风险指数，description为风险评估报告信息";
    //private static final String SystemMessage = "你是助手";


    /**
     * 聊天接口，流式接口，通过回调函数获取结果
     * @param message 提问的问题
     */
    public void chatWithDeepseek(String message,DataReceivedCallback callback) {
        //初始化Generation实例gen和Message实例userMsg
        Generation gen = new Generation();
        // 系统消息
        Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content(SystemMessage).build();
        // 用户消息
        Message userMsg = Message.builder().role(Role.USER.getValue()).content(message).build();

        try {
            // 实现DataReceivedCallback接口，并处理每次接收到的数据，将消息返回
            this.streamCallWithCallback(gen, systemMsg, userMsg, callback);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }



    /**
     * 异步调用，通过回调函数获取结果
     * @param gen
     * @param userMsg
     * @param callback 回调函数
     * @throws NoApiKeyException
     * @throws ApiException
     * @throws InputRequiredException
     * @throws InterruptedException
     */
    public void streamCallWithCallback(Generation gen, Message systemMsg, Message userMsg, DataReceivedCallback callback)
            throws NoApiKeyException, ApiException, InputRequiredException, InterruptedException {
        Constants.apiKey=this.API_KEY;
        //构造API请求参数，系统信息+用户信息
        GenerationParam param = buildGenerationParam(systemMsg,userMsg);
        //初始化一个信号量，用于在异步操作完成后通知主线程
        Semaphore semaphore = new Semaphore(0);
        StringBuffer fullContent = new StringBuffer();
        // 调用API，并通过回调函数返回结果
        gen.streamCall(param, new ResultCallback<GenerationResult>() {
            //有结果响应时：
            @Override
            public void onEvent(GenerationResult message) {
                String msg = message.getOutput().getChoices().get(0).getMessage().getContent();
                fullContent.append(msg);
                //返回每次接收到的消息
                try {
                    callback.onDataReceived(msg);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            //异常处理
            @Override
            public void onError(Exception err) {
                log.error("deepseek错误：", err.getMessage());
                semaphore.release();
            }

            //API调用完全结束后
            @Override
            public void onComplete() {
                log.info("Completed");
                try {
                    callback.onProcessCompleted(fullContent.toString());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                semaphore.release();
            }
        });

        // 主线程在此等待，直到信号量被释放。
        semaphore.acquire();
    }

    /**
     * 构造API请求参数
     * @param userMsg
     * @return
     */
    private  GenerationParam buildGenerationParam(Message systemMsg,Message userMsg) {
        return GenerationParam.builder()
                .model("deepseek-v3")
                .messages(Arrays.asList(systemMsg,userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .topP(0.8)
                .incrementalOutput(true)
                .build();
    }

    public static String scanImageForAnimal(String imagePath,DataReceivedCallback callback)
            throws ApiException, NoApiKeyException, UploadFileException, IOException {
        MultiModalConversation conv = new MultiModalConversation();
        MultiModalMessage systemMessage = MultiModalMessage.builder().role(Role.SYSTEM.getValue())
                .content(Arrays.asList(
                        Collections.singletonMap("text", "你是一个宠物狗危险性评估助手，请根据图片评估图片中的动物狗危险性"))).build();
        MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
                .content(Arrays.asList(
                        Collections.singletonMap("image", imagePath),
                        Collections.singletonMap("text", "图片中的狗，危险性如何？"))).build();
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                // 若没有配置环境变量，请用百炼API Key将下行替换为：.apiKey("sk-xxx")
                .apiKey(API_KEY)
                .model("qwen-vl-max-latest")  // 此处以qwen-vl-max-latest为例，可按需更换模型名称。模型列表：https://help.aliyun.com/model-studio/getting-started/models
                .messages(Arrays.asList(systemMessage, userMessage))
                .incrementalOutput(true)
                .build();
        final String[] aiText = new String[1];
        Flowable<MultiModalConversationResult> result = conv.streamCall(param);
        result.blockingForEach(item -> {
            try {
                String text = "";
                if(!item.getOutput().getChoices().get(0).getMessage().getContent().isEmpty()){
                    text = (String) item.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text");
                }
                System.out.println(text);
                callback.onDataReceived(text);
                aiText[0] += text;
            } catch (Exception e){
                callback.onError(e);
            }
        });
        callback.onProcessCompleted(aiText[0]);
        return aiText[0];
    }


//    /**
//     * 单次聊天，一次性传输消息
//     * @param message
//     * @return
//     * @throws NoApiKeyException
//     * @throws InputRequiredException
//     */
//    public String chat(String message) throws NoApiKeyException, InputRequiredException {
//        //设置apikey
//        Constants.apiKey=apikey;
//        Generation gen = new Generation();
//        MessageManager msgManager = new MessageManager(10);
//        Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content("You are a helpful assistant.").build();
//        Message userMsg = Message.builder().role(Role.USER.getValue()).content(message).build();
//        msgManager.add(systemMsg);
//        msgManager.add(userMsg);
//        QwenParam param =
//                QwenParam.builder().model(Generation.Models.QWEN_TURBO).messages(msgManager.get())
//                        .resultFormat(QwenParam.ResultFormat.MESSAGE)
//                        .build();
//        GenerationResult result = gen.call(param);
//        System.out.println(result.getOutput().getChoices().getFirst().getMessage().getContent());
//        return String.valueOf(result.getOutput().getChoices().getFirst().getMessage().getContent());
//    }



}
